//
// Created by song on 16-11-18.
//

#ifndef C0COMPILER_CONFIG_H
#define C0COMPILER_CONFIG_H

#include <vector>
#include <sstream>
//#include <boost/program_options.hpp>

const int MAX_SOURCE_FILE_SIZE = 100000;
const int TYPE_PRINT_LENGTH = 20;
using namespace std;

//namespace po = boost::program_options;

class Config{
public:
    static string sourceFileName;
    static string asmFileName;
    static bool showAllError;
    static bool printAST;
    static bool printSource;
    static bool printSymbolTable;
    static bool printASTDetail;
    static bool printTokens;
    static bool printIR;
    static bool printASM;
    static bool levelOneOptimize;
    static bool irSymbolTable;
    static bool printBasicBlocks;
    static bool printControlFlowChart;
    static bool printDefUseChains;
    static bool printMergedDFChain;
    static bool printConflictGraph;

    static void parseCmdArgs(int argc, char* argv[]){
        for(int i=0; i<argc; i++){
            parseOneArg(argv[i]);
        }
    }

    static void parseStdInArgs(string argsLine){
        vector<string> argsList;
        split(argsLine, ' ', argsList);
        for(int i=0; i<argsList.size(); i++){
            parseOneArg(argsList[i]);
        }
    }

    static void parseCmdArgsBoost(int argc, char* argv[]){
//        po::options_description desc("选项");
//        desc.add_options()
//                ("help,h", "print help messages")
//                ("input,i", po::value<string>(&sourceFileName), "C0 source file name/path")
//                ("output,o", po::value<string>(&asmFileName), "output assemble file name/path")
//                ("showerr,e", po::value<string>(&showError)->default_value("none"), "show all|first|none(default) error messages")
//                ("printAST,a", po::value<bool>(&printAST)->default_value(false), "if true then print AST, default false")
//                ;
//        po::variables_map vm;
//        po::store(po::parse_command_line(argc, (const char *const *) argv, desc), vm);
//        po::notify(vm);
    }

private:
    static void parseOneArg(string arg){
        if(endWith(arg, ".asm")){
            asmFileName = arg;
        }else if(endWith(arg, ".c0")) {
            sourceFileName = arg;
        }else if(endWith(arg, ".c0'")){
            sourceFileName = arg.substr(1, arg.size()-2);
        }else if(arg=="-ast"){
            printAST = true;
        }else if(arg=="-AST"){
            printASTDetail=true;
        }else if(arg=="-source"){
            printSource =true;
        }else if(arg=="-sym"){
            printSymbolTable = true;
        }else if(arg=="-err"){
            showAllError=true;
        }else if(arg=="-ir"){
            printIR = true;
        }else if(arg=="-asm"){
            printASM = true;
        }else if(arg=="-o1"){
            levelOneOptimize = true;
        }else if(arg=="-irSym"){
            irSymbolTable = true;
        }else if(arg=="-block"){
            printBasicBlocks = true;
        }else if(arg=="-cf"){
            printControlFlowChart = true;
        }else if(arg=="-du"){
            printDefUseChains = true;
        }else if(arg=="-mdu"){
            printMergedDFChain = true;
        }else if(arg=="-token"){
            printTokens = true;
        }else if(arg=="-cg"){
            printConflictGraph = true;
        }
    }

    static bool endWith(std::string const &fullString, std::string const &ending) {
        if (fullString.length() >= ending.length()) {
            return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending));
        } else {
            return false;
        }
    }

    static bool startWith(string const & fullStr, string const & prefix){
        return (!fullStr.compare(0, prefix.size(), prefix));
    }

    static void split(const std::string &s, char delim, std::vector<std::string> &elems) {
        std::stringstream ss;
        ss.str(s);
        std::string item;
        while(std::getline(ss, item, delim)) {
            elems.push_back(item);
        }
    }

};

#endif //C0COMPILER_CONFIG_H

